﻿//#define TEST_PROGRESS_UPDATE
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Globalization;

using LedCenter.GUI;

using LetiLib.Device;
using LetiLib.Database;
using LetiLib.Data;
using LetiLib.Connection;
using LetiLib.Utils;

namespace LedCenter
{
    public partial class MainForm : Form
    {

        private const int SERVER_DEFAULT_PORT = 6868;

        private TcpListener tcpServer;
        private TcpClient tcpClient;
        private NetworkStream clientStream;
        private Thread serverThread;
        //private ArrayList threadArray = new ArrayList();
        /*
        public TcpClient connectedClient
        {
            get { return tcpClient; }
            set { tcpClient = value; }
        }
        */
        private bool isStarted = false;
        public MainForm()
        {
            InitializeComponent();
            isStarted = false;
            // Add event handler for child panel.
            this.homePanel.btnStart.Click += new EventHandler(btnStartServer_Click);
            this.progPanel.SendData += new EventHandler(progPanel_SendData);

            this.deviceDetailsPanel.ledPageControl.ActiveImage += new LedPageControl.ImageActiveHandler(ledPageControl_ActiveImage);
            this.deviceDetailsPanel.ledPageControl.ActivePage += new LedPageControl.PageActiveHandler(ledPageControl_ActivePage);
            this.deviceDetailsPanel.ledPageControl.OnPageCreated += new LedPageControl.CreatePageHandler(ledPageControl_OnPageCreated);
            this.deviceDetailsPanel.ledPageControl.OnPageHeaderUpdate += new LedPageControl.UpdatePageHeaderHandler(ledPageControl_OnPageHeaderUpdate);
            this.deviceDetailsPanel.ledPageControl.OnPageDeleted += new LedPageControl.DeletePageHandler(ledPageControl_OnPageDeleted);
            this.deviceDetailsPanel.ledPageControl.OnGetActivePage += new LedPageControl.GetActivePageHandler(ledPageControl_OnGetActivePage);
            this.deviceDetailsPanel.ledPageControl.OnPopupAdded += new LedPageControl.AddPopupHandler(ledPageControl_OnPopupAdded);
            this.deviceDetailsPanel.ledPageControl.OnPopupUpdate += new LedPageControl.UpdatePopupHandler(ledPageControl_OnPopupUpdate);
            this.deviceDetailsPanel.ledPageControl.OnPopupDeleted += new LedPageControl.DeletePopupHandler(ledPageControl_OnPopupDeleted);
            this.deviceDetailsPanel.ledPageControl.OnGetPageInfo += new LedPageControl.GetPageInfoHandler(ledPageControl_OnGetPageInfo);
            this.deviceDetailsPanel.ledPageControl.OnDeleteImage += new LedPageControl.DeleteImageHandler(ledPageControl_OnDeleteImage);
            this.deviceDetailsPanel.ledPageControl.OnDeleteAllImage += new LedPageControl.DeleteAllImageHandler(ledPageControl_OnDeleteAllImage);
            this.deviceDetailsPanel.ledPageControl.OnGetImageList += new LedPageControl.GetImageListHandler(ledPageControl_OnGetImageList);
            this.deviceDetailsPanel.ledPageControl.OnImageUpdate += new LedPageControl.UpdateImageHandler(ledPageControl_OnImageUpdate);
            this.deviceDetailsPanel.ledPageControl.OnImageAdd += new LedPageControl.AddImageToPlaylistHandler(ledPageControl_OnImageAdd);
            this.deviceDetailsPanel.ledPageControl.OnImageDelete += new LedPageControl.DeleteImageFromPlaylistHandler(ledPageControl_OnImageDelete);
            this.deviceDetailsPanel.ledPageControl.OnGetStatus += new LedPageControl.GetStatusHandler(ledPageControl_OnGetStatus);
            this.deviceDetailsPanel.ledPageControl.OnCaptureScreen += new LedPageControl.CaptureScreenHandler(ledPageControl_OnCaptureScreen);
            this.deviceDetailsPanel.ledPageControl.OnReboot += new LedPageControl.RebootHandler(ledPageControl_OnReboot);
            this.deviceDetailsPanel.ledPageControl.OnClearScreen += new LedPageControl.ClearScreenHandler(ledPageControl_OnClearScreen);
            this.deviceDetailsPanel.ledPageControl.OnScanScreen += ledPageControl_OnScanScreen;
            this.deviceDetailsPanel.ledPageControl.OnCheckLed += ledPageControl_OnCheckLed;
            this.deviceDetailsPanel.ledPageControl.OnSetPredefine += ledPageControl_OnSetPredefine;
            //this.deviceDetailsPanel.busControl.OnGetStatus += new BusControl.GetStatusHandler(ledPageControl_OnGetStatus);
            //this.deviceDetailsPanel.busControl.BusUpdate += new BusControl.BusUpdateHandler(busControl_BusUpdate);

            // Show the Home panel when beginning
            showHomePanel();
        }

        
        #region | Device's page and bus controls |

        void ledPageControl_OnScanScreen()
        {
            // TODO: Send reboot command
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendScanScreenCmd();
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnClearScreen()
        {
            // TODO: Send reboot command
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendClearScreenCmd();
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnReboot()
        {
            // TODO: Send reboot command
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendRebootCmd();
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnCaptureScreen()
        {
            // TODO: Send capture screen command
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendCaptureScreenCmd();
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }
        
        void ledPageControl_OnGetStatus()
        {
            /*
            ledStatusData = new byte[] { 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
            ledStatusWidth = 128;
            ledStatusHeight = 64;
            processCheckLedData(0);
            return;
             */
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendGetStatusCmd();
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnCheckLed()
        {
            // TODO: Send reboot command
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendCheckLedCmd();
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnGetImageList()
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendGetImageListCmd();
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnDeleteAllImage()
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendDeleteAllImageCmd();
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnSetPredefine(ushort imgageID, byte romID)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendSetPredefineCmd(imgageID, romID);
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnDeleteImage(ushort pageID)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendDeleteImageCmd(pageID);
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }
        
        void ledPageControl_OnGetPageInfo(ushort pageID)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendPageInfoCmd(pageID);
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnPopupDeleted(ushort pageID, ushort popupID)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendDeletePopupCmd(pageID, popupID);
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnPopupUpdate(ushort pageID, ushort popupID, POPUP popupData)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendUpdatePopupCmd(pageID, popupID, popupData);
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnImageAdd(ushort pageID, ushort popupID, IMAGE imageData)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendInsertImageToPlaylistCmd(pageID, popupID, imageData);
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnImageUpdate(ushort pageID, ushort popupID, byte playOrder, IMAGE imageData)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendUpdateImageCmd(pageID, popupID, playOrder, imageData);
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnImageDelete(ushort pageID, ushort popupID, byte playOrder)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendDeleteImageFromPlaylistCmd(pageID, popupID, playOrder);
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnPopupAdded(ushort pageID, ushort popupID, POPUP popupData)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendInsertPopupCmd(pageID, popupID, popupData);
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnGetActivePage()
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendGetActivePageCmd();
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_OnPageCreated(LETIPage page)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendCreatePageCmd(page);
            else
            {
                MessageBox.Show("Please check device status!");
            }
            XmlDatabase.Instance.addPage(dev.IMEI, page);
            //dev.pages.Add(page);
            this.deviceDetailsPanel.ledPageControl.DataSource = dev.pages;

        }

        void ledPageControl_OnPageDeleted(ushort pageID)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendDeletePageCmd(pageID);
            else
            {
                MessageBox.Show("Please check device status!");
            }
            //dev.pages.RemoveAt(pageID);
            this.deviceDetailsPanel.ledPageControl.DataSource = dev.pages;
        }

        void ledPageControl_OnPageHeaderUpdate(ushort pageID, LETIPageHeader pageHeader)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendUpdatePageHeaderCmd(pageID, pageHeader);
            else
            {
                MessageBox.Show("Please check device status!");
            }
            //XmlDatabase.Instance.addPage(dev.IMEI, page);
            //dev.pages.Add(page);
            //this.deviceDetailsPanel.ledPageControl.DataSource = dev.pages;
        }  

        void ledPageControl_ActivePage(ushort pageID)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendActivePage(pageID);
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        void ledPageControl_ActiveImage(ushort pageID, ushort popupID, ushort imgID)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendActiveImage(pageID,popupID,imgID);
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        // TungPT deleted >>
        //void busControl_BusUpdate(string busContent)
        //{
        //    // TODO: display device detail at selected index
        //    if (lastSeletecteIndex < 0)
        //    {
        //        MessageBox.Show("Please choose device!");
        //        return;
        //    }
        //    //int selectedindex = listViewDevices.SelectedIndices[0];
        //    TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
        //    if (dev != null && dev.isActive)
        //        dev.SendBusData(busContent);
        //    else
        //    {
        //        MessageBox.Show("Please check device status!");
        //    }
        //}
        // << ended
        void busControl_BusUpdate(string busContent)
        {
            // TODO: display device detail at selected index
            if (lastSeletecteIndex < 0)
            {
                MessageBox.Show("Please choose device!");
                return;
            }
            //int selectedindex = listViewDevices.SelectedIndices[0];
            TCPDevice dev = (TCPDevice)listDevice[lastSeletecteIndex];
            if (dev != null && dev.isActive)
                dev.SendBusData(busContent);
            else
            {
                MessageBox.Show("Please check device status!");
            }
        }

        #endregion

        void progPanel_SendData(object sender, EventArgs e)
        {
            // check if current mode is TEXT or IMAGES
            PlaylistData playlist = null;
            DataInfo info;
            ProgramData prog = null;
            if (progPanel.currentMode == PROGRAM_MODE.TEXT)
            {
                info = new DataInfo((ushort)progPanel.letiLed.Index,(ushort)progPanel.letiLed.Resolution.Width, (ushort)progPanel.letiLed.Resolution.Height, LETILed.BPP);
                prog = new ProgramData(info, progPanel.letiLed.getBytes());
            }
            else
            {
                playlist = new PlaylistData();
                List<ProgramData> programs = new List<ProgramData>();

                #region | Test code |
                // Test code >>
                /*
                info = new DataInfo(1, (ushort)progPanel.letiLed.Resolution.Width, (ushort)progPanel.letiLed.Resolution.Height, (ushort)bpp);
                prog = new ProgramData(info, progPanel.letiLed.getBytes());
                playlist.packages.Add(prog);

                info = new DataInfo(2, (ushort)progPanel.letiLed.Resolution.Width, (ushort)progPanel.letiLed.Resolution.Height, (ushort)bpp);
                prog = new ProgramData(info, progPanel.letiLed.getRedArray());
                playlist.packages.Add(prog);

                info = new DataInfo(3, (ushort)progPanel.letiLed.Resolution.Width, (ushort)progPanel.letiLed.Resolution.Height, (ushort)bpp);
                prog = new ProgramData(info, progPanel.letiLed.getGreenArray());
                playlist.packages.Add(prog);

                info = new DataInfo(4, (ushort)progPanel.letiLed.Resolution.Width, (ushort)progPanel.letiLed.Resolution.Height, (ushort)bpp);
                prog = new ProgramData(info, progPanel.letiLed.getYellowArray());
                playlist.packages.Add(prog);
                */
                // << end test
                #endregion

                // get selected item from thumbnail
                List<Image> selectedImage = this.progPanel.images;
                Bitmap selectedBitmap = null;
                for (int i = 0; i < selectedImage.Count; i++)
                {
                    // foreach item, generate package data and add to playlist
                    // get bitmap
                    selectedBitmap = (Bitmap)selectedImage[i];
                    // create data info
                    info = new DataInfo((ushort)(i + 1),
                        (ushort)selectedBitmap.Width,
                        (ushort)selectedBitmap.Height,LETILed.BPP);
                    // create program data
                    
                    prog = new ProgramData(info, LETILed.getByteFromBitmap(selectedBitmap));
                    // add to playlist
                    playlist.packages.Add(prog);
                }
                playlist.Info.Delay = 5;
                playlist.Info.PackageCount = (ushort)playlist.packages.Count;
                
            }
            // Create led program base on progPanel's leti led data
            
            UpdateProgress up = new UpdateProgress();
#if TEST_PROGRESS_UPDATE
            Random ran = new Random();
            foreach (TCPDevice dev in selectTCPDevices())
            {
                up.Add(dev);
                dev.startProgramSim();
            }
            up.ShowDialog();
            
#else
            // allow user to choose which devices need to updated and send update data
            foreach (TCPDevice dev in selectTCPDevices())
            {
                if (progPanel.currentMode == PROGRAM_MODE.TEXT)
                {
                    if (prog != null && dev != null && dev.isActive)
                    {
                        if (progPanel.cbPredefined.Checked)
                            dev.sendPredefined(prog, (ushort)progPanel.numBrightness.Value, (ushort)progPanel.letiLed.Index);
                        else
                            dev.sendProgramSync(prog);
                    }
                    else
                        Debug.WriteLine("Send null program");
                }
                else
                {
                    if (playlist != null)
                        dev.sendPrograms(playlist);
                    else
                        Debug.WriteLine("Send null playlist");
                }
            }
            //up.ShowDialog();
#endif
        }

        List<TCPDevice> selectTCPDevices()
        {
            List<TCPDevice> devs = new List<TCPDevice>();
            DeviceSelector sel = new DeviceSelector();
            foreach (BaseDevice dev in listDevice)
            {
                if (dev.GetType() == typeof(TCPDevice))
                {
                    sel.addDevice((TCPDevice) dev);
                }
            }

            if (sel.ShowDialog() == DialogResult.OK)
            {
                if (sel.listSelectedDevices.Count == 0)
                    MessageBox.Show("Please choose device to send");
                devs.AddRange(sel.listSelectedDevices);
            }
            return devs;
        }
           
        #region | Server Start/Stop |
        /// <summary>
        /// Start and stop server
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        void btnStartServer_Click(object sender, EventArgs e)
        {
            if (isStarted)
            {
                isStarted = !isStarted;
                StopServer();
                homePanel.btnStart.Text = "Start server";
            }
            else
            {
                isStarted = !isStarted;
                StartServer();
                homePanel.btnStart.Text = "Stop server";
            }
        }

        /// This function spawns new thread for TCP communication
        public void StartServer()
        {
            //tbPortNumber.Enabled = false;
            serverThread = new Thread(new ThreadStart(StartListen));
            //checkingFlag = true;
            //checkingThread = new Thread(new ThreadStart(CheckSocketStatus));
            serverThread.Start();
            //checkingThread.Start();

        }

        /// Server listens on the given port and accepts the connection from Client.
        public void StartListen()
        {

            //IPAddress localAddr = IPAddress.Parse("192.168.175.38");

            tcpServer = new TcpListener(SERVER_DEFAULT_PORT);
            tcpServer.Start();

            IPHostEntry host;
            string localIP = "";
            host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (IPAddress ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    localIP += ip.ToString() + " | ";
                }
            }

            string IP = ((IPEndPoint)tcpServer.LocalEndpoint).Address.ToString();
            string Port = SERVER_DEFAULT_PORT.ToString();
            this.homePanel.SetTitle("Server start at: " + localIP + " Port: " + Port);
            NetworkStream ns = null;
            byte[] data = new byte[17];
            StringBuilder dataString = new StringBuilder();
            // Keep on accepting Client Connection
            while (isStarted)
            {
                
                // New Client connected, call Event to handle it.
                Thread t = new Thread(new ParameterizedThreadStart(NewClient));
                tcpClient = tcpServer.AcceptTcpClient();
                
                string remoteIP = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString();
                string remotePort = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Port.ToString();
                homePanel.SetInfo(remoteIP + "\\" + remotePort, "Try to connect!");
                ns = tcpClient.GetStream();
                //homePanel.SetInfo("system", ns.ReadTimeout.ToString());
                ns.ReadTimeout = 20000;// HARDCODE

                int readCount;
                MyEventArgs mEvent = null;
                dataString.Clear();
                try
                {
                    // HARD CODE
                    while ((readCount = ns.Read(data, 0, 17)) != 0)
                    {
                        if (Receiver.bAcceptIMEI(data))
                        {
                            dataString.Append(Encoding.ASCII.GetString(data, 2, 15));
                            if (tcpClient != null)
                            {
                                homePanel.SetInfo(remoteIP + "\\" + remotePort, "Read data: " + dataString.ToString());
                                mEvent = new MyEventArgs(tcpClient, dataString.ToString());
                            }
                            break;
                        }
                    }
                }catch(Exception ex)
                {
                    homePanel.SetInfo(remoteIP + "\\" + remotePort, "Read IMEI time out!");
                    tcpClient.Close();
                    Debug.WriteLine("MainForm: 256: " +ex.Message);
                    Debug.WriteLine(ex.StackTrace);
                }
                if (mEvent != null)
                    t.Start(mEvent);

            }

        }                                               

        /// Function to stop the TCP communication. It kills the thread   and closes client connection
        public void StopServer()
        {
            if (tcpServer != null)
            {
                for (int i = 0; i < listDevice.Count; i++)
                {
                    if (listDevice[i].GetType() == typeof(TCPDevice))
                    {
                        string addr = ((TCPDevice)listDevice[i]).IP;
                        string port = ((TCPDevice)listDevice[i]).Port.ToString();
                        DisconnectClient(addr, port);
                    }
                }
                /*
                // Abort All Running Threads
                foreach (Thread t in threadArray)
                {
                    t.Abort();
                }
                */
                
                // Abort Listening Thread and Stop listening
                if (serverThread.IsAlive)
                    serverThread.Abort();
                tcpServer.Stop();
                this.homePanel.SetTitle("Server stopped");
                // TO DO:
                // change devices status to offline

                
                //checkingFlag = false;
            }
            //tbPortNumber.Enabled = true;
        }


        public void NewClient(Object obj)
        {
            ClientAdded(this, (MyEventArgs)obj);
        }


        /// Event Fired when a Client gets connected. Following action is performed
        /// Update list view
        public void ClientAdded(object sender, EventArgs e)
        {
            String remoteIP = "", remotePort = "";
            tcpClient = ((MyEventArgs)e).clientSock;
            
            string imei = ((MyEventArgs)e).IMEI;
            bool checkFlag = false;
            int threadIndex = -1;
            foreach (BaseDevice dev in listDevice)
            {
                threadIndex++;
                if (dev.GetType() == typeof(TCPDevice))
                {
                    if (imei.Equals(((TCPDevice)dev).IMEI))
                    {
                        ((TCPDevice)dev).close();
                        ((TCPDevice)dev)._tcpClient = tcpClient;
                        ((TCPDevice)dev).DataTimeout += new DataTimeoutHandler(MainForm_DataTimeout);
                        checkFlag = true;
                        dev.isActive = true;
                        remoteIP = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString();
                        remotePort = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Port.ToString();
                        homePanel.SetInfo(remoteIP + "\\" + remotePort, "Connected!");
                        ShowNotify(remoteIP + "\\" + remotePort +" Connected!");
                        //ClientReceive(threadIndex );
                        return;
                    }
                }
            }
            // if the client is not in device list, we reject
            if (!checkFlag)
            {
                tcpClient.Client.Disconnect(false);
                homePanel.SetInfo(remoteIP + "\\" + remotePort, "not in list. Rejected!");
                return;
            }
            /*
            threadIndex = -1;
            // TO DO
            // Call Delegate Function to update Tree View
            // lock (listDevice)
            {
                lock (threadArray)
                {
                    threadArray.Add(Thread.CurrentThread);
                    threadIndex = threadArray.Count;
                }
                // TODO:
                //UpdateClientList(remoteIP + " : " + remotePort, "Add");
                homePanel.SetInfo(remoteIP + "\\" + remotePort, "Connected!");
            }
            ClientReceive(threadIndex-1);
            */
        }

        void MainForm_DataTimeout(object sender, EventArgs e)
        {
            TCPDevice client = sender as TCPDevice;
            if (client != null)
            {
                homePanel.SetInfo(client.IP + "\\" + client.Port, "Disconnected by timer!");
                //MessageBox.Show("Disconnecting  " + remoteIP + "\\" + remotePort);
            }
            
        }

        private void ClientReceive(int index)
        {
            //connectedClient = tcpClient;
            if (tcpClient == null || !tcpClient.Connected) return;
            clientStream = tcpClient.GetStream();

            // Create the state object.
            StateObject state = new StateObject();
            state.index = index;
            //state.workSocket = connectedClient.Client;
            //state.threadIndex = index;
            //Call Asynchronous Receive Function
            try
            {
                IAsyncResult iar = ((TCPDevice)listDevice[state.index])._tcpClient.Client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                                    new AsyncCallback(OnReceive), state);
                ((TCPDevice)listDevice[state.index]).IAR = iar;
                iar.AsyncWaitHandle.WaitOne();
            }
            catch (System.Exception ex)
            {
                MessageBox.Show("Couldn't start the async receive");
            }



        }

        public void OnReceive(IAsyncResult ar)
        {
            Debug.WriteLine(" >> 1 ");
            String content = String.Empty;
            string sck = "";

            // Retrieve the state object and the handler socket
            // from the asynchronous state object.
            StateObject state = (StateObject)ar.AsyncState;
            // reject unknow thread index
            if (state.index == -1) return;
            Socket handler;
            try
            {
                handler = ((TCPDevice)listDevice[state.index])._tcpClient.Client;
            }catch (Exception we)
            {
                Debug.WriteLine(" >> 1 error ");
                return;
            }
            Debug.WriteLine(" >> 2 ");
            //state.isThreadWaitingForAbort = false;

            int bytesRead=0;
            String remoteIP = "", remotePort = "";
            remoteIP = ((IPEndPoint)handler.RemoteEndPoint).Address.ToString();
            remotePort = ((IPEndPoint)handler.RemoteEndPoint).Port.ToString();
            sck = remoteIP + "\\" + remotePort;
            if (handler.Connected)
            {
                Debug.WriteLine(" >> 3 ");
                // Read data from the client socket. 
                try
                {
                    if (ar == ((TCPDevice)listDevice[state.index]).IAR)
                    {
                        Debug.WriteLine("end ");
                        bytesRead = handler.EndReceive(ar);
                       
                    }
                    Debug.WriteLine(" >> 4 ");
                    if (bytesRead > 0)
                    {
                        Debug.WriteLine(" >> 5 ");
                        byte[] btReceive;
                        // There  might be more data, so store the data received so far.
                        state.sb.Remove(0, state.sb.Length);
                        state.sb.Append(Encoding.Default.GetString(
                                         state.buffer, 0, bytesRead));

                        content = state.sb.ToString();
                        //Error Tolerance Handling (GSM Module Case Only)
                        if (content[0] == '\n')
                        {
                            string tmp = content.Substring(1);
                            btReceive = Encoding.Default.GetBytes(tmp);
                        }
                        else
                            btReceive = Encoding.Default.GetBytes(content);

                        Debug.WriteLine(" >> 6 ");
                        // TO DO: process data here
                        ((TCPDevice)listDevice[state.index]).processData(btReceive);

                        COMMAND ret = checkCommand(btReceive);
                        // Handle response data


                        if (ret == COMMAND.WARNING_DAMAGED || ret == COMMAND.WARNING_OPENNED ||
                            ret == COMMAND.WARNING_TOO_HOT || ret == COMMAND.WARNING_OUT_OF_POWER)
                        {
                            homePanel.Warning(((TCPDevice)listDevice[state.index]).IP, ret.ToString());
                        }
                        else if (ret == COMMAND.CMD_GET_ACTIVE_PAGE)
                        {
                            homePanel.Warning(((TCPDevice)listDevice[state.index]).Name, "Current active page: " + BitConverter.ToUInt16(btReceive,2));
                            MessageBox.Show("Current active page: " + BitConverter.ToUInt16(btReceive,2),((TCPDevice)listDevice[state.index]).Name);
                        }
                        else if (ret == COMMAND.CMD_GET_PAGE_INFO)
                        {
                            LETIPage page = new LETIPage(btReceive);
                            homePanel.Warning(((TCPDevice)listDevice[state.index]).Name, "Page info: \n" + page.ToString());
                            MessageBox.Show("Page info: \n" + page.ToString(),((TCPDevice)listDevice[state.index]).Name );
                        }
                        else if (ret == COMMAND.CMD_GET_LIST_IMAGE_INDEX)
                        {
                            //ushort[] indexArr = new ushort[];
                            homePanel.Warning(((TCPDevice)listDevice[state.index]).Name, "List image index: \n" + btReceive);
                            StringBuilder stringbd = new StringBuilder();
                            foreach(byte b in btReceive)
                                stringbd.Append(b + " ");
                            MessageBox.Show("List image index: \n" + stringbd, ((TCPDevice)listDevice[state.index]).Name);
                        }
                        else if (ret == COMMAND.LED_INFO_HEADER)
                        {
                            isCheckLedMode = false;
                            //ushort[] indexArr = new ushort[];
                            string hex = BitConverter.ToString(btReceive);
                            hex.Replace(" ", "");
                            homePanel.Warning(((TCPDevice)listDevice[state.index]).Name, "Check led header: \n" + hex);
                            //MessageBox.Show("List image index: \n" + btReceive, ((TCPDevice)listDevice[state.index]).Name);
                            ledStatusWidth = BitConverter.ToUInt16(btReceive, 2);
                            ledStatusHeight = BitConverter.ToUInt16(btReceive, 4);
                            ledStatusPackageCount = btReceive[6];
                            LED_STATUS_DATA_PACKAGE_LENGTH = BitConverter.ToUInt16(btReceive, 7);
                            homePanel.Warning(((TCPDevice)listDevice[state.index]).Name,
                                "   Width: " + ledStatusWidth + "\n" +
                                "   Height: " + ledStatusHeight + "\n" +
                                "   Count: " + ledStatusPackageCount + "\n" +
                                "   Pkg length: " + LED_STATUS_DATA_PACKAGE_LENGTH + "\n");
#if !TOANNV
                            ledStatusDataLength = ((ledStatusWidth + 7) / 8) * ledStatusHeight;
                            if ((ledStatusDataLength + LED_STATUS_DATA_PACKAGE_LENGTH - 1) / LED_STATUS_DATA_PACKAGE_LENGTH == ledStatusPackageCount)
                            {
                                isCheckLedMode = true;
                                ledStatusData = new byte[ledStatusDataLength];
                            }
#else
                            ledStatusDataLength = ((ledStatusWidth + 3) / 4) * ledStatusHeight;
                            if ((ledStatusDataLength + LED_STATUS_DATA_PACKAGE_LENGTH - 1) / LED_STATUS_DATA_PACKAGE_LENGTH == ledStatusPackageCount)
                            {
                                isCheckLedMode = true;
                                ledStatusData = new byte[ledStatusDataLength];

                            }
#endif
                        }
                        else if ((ret == COMMAND.LED_SCREEN_DATA || ret == COMMAND.LED_STATUS_DATA) && isCheckLedMode && 
                            ledStatusPackageCount > 0 &&ledStatusDataLength > 0)
                        {
                            //ushort[] indexArr = new ushort[];
                            
                            string hex = BitConverter.ToString(btReceive);
                            hex.Replace(" ", "");
                            
                            //MessageBox.Show("List image index: \n" + btReceive, ((TCPDevice)listDevice[state.index]).Name);
                            
                            currentLedStatusPackageIndex = BitConverter.ToUInt16(btReceive,2);
                            //btReceive.CopyTo(ledStatusData, packageIndex * LED_STATUS_DATA_PACKAGE_LENGTH);
                            Buffer.BlockCopy(btReceive, 4,
                                ledStatusData, currentLedStatusPackageIndex * LED_STATUS_DATA_PACKAGE_LENGTH, btReceive.Length - 4);
                            homePanel.Warning(((TCPDevice)listDevice[state.index]).Name, "\n\nCheck led Data: \n" + hex + "\n" + 
                                "   Index: " + currentLedStatusPackageIndex);
                            if (currentLedStatusPackageIndex == ledStatusPackageCount-1)
                            {
                                hex = BitConverter.ToString(ledStatusData);
                                hex.Replace(" ", "");
                                homePanel.Warning(((TCPDevice)listDevice[state.index]).Name, "Total Check led Data: \n" + hex);
                                Thread t = new Thread(new ParameterizedThreadStart(processCheckLedData));
                                t.SetApartmentState(ApartmentState.STA);
                                t.Start(state.index);  
                                //processCheckLedData();
                            }
                        }
                        else
                            homePanel.SetText(((TCPDevice)listDevice[state.index]).IP, btReceive);

                        Debug.WriteLine(" >> 7 ");
                        IAsyncResult iar = handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                                new AsyncCallback(OnReceive), state);
                        ((TCPDevice)listDevice[state.index]).IAR = iar;
                        iar.AsyncWaitHandle.WaitOne();
                        Debug.WriteLine(" >> 8 ");
                    }
                }

                catch (SocketException socketException)
                {
                    //WSAECONNRESET, the other side closed impolitely
                    if (socketException.ErrorCode == 10054 || ((socketException.ErrorCode != 10004) && (socketException.ErrorCode != 10053)))
                    {
                        Debug.WriteLine("Mainform 772: " + socketException.Message + "\n" + socketException.StackTrace);
                        // Complete the disconnect request.
                        DisconnectClient(remoteIP, remotePort);

                        handler.Close();
                        handler = null;
                    }
                }

                catch (Exception exception)
                {
                    Debug.WriteLine("Mainform 784: " + exception.Message + "\n" + exception.StackTrace);
                }
            }
        }

        private COMMAND checkCommand(byte[] btReceive)
        {
            if (Receiver.bAcceptWarningTooHot(btReceive))
            {
                return COMMAND.WARNING_TOO_HOT;
            }
            else if (Receiver.bAcceptWarningDamaged(btReceive))
            {
                return COMMAND.WARNING_DAMAGED;
            }
            else if (Receiver.bAcceptWarningPowerLost(btReceive))
            {
                return COMMAND.WARNING_OUT_OF_POWER;
            }
            else if (Receiver.bAcceptWarningOpenned(btReceive))
            {
                return COMMAND.WARNING_OPENNED;
            }
            else if (Receiver.bAcceptGetActivePageResponse(btReceive))
            {
                return COMMAND.CMD_GET_ACTIVE_PAGE;
            }
            else if (Receiver.bAcceptGetPageInfoResponse(btReceive))
            {
                return COMMAND.CMD_GET_PAGE_INFO;
            }
            else if (Receiver.bAcceptGetListImageIndexResponse(btReceive))
            {
                return COMMAND.CMD_GET_LIST_IMAGE_INDEX;
            }
            else if (Receiver.bAcceptCheckledInfo(btReceive))
            {
                return COMMAND.LED_INFO_HEADER;
            }
            else if (Receiver.bAcceptCheckledDataPackage(btReceive))
            {
                return COMMAND.LED_SCREEN_DATA;
            }
            else if (Receiver.bAcceptScreenDataPackage(btReceive))
            {
                return COMMAND.LED_SCREEN_DATA;
            }
            return COMMAND.SERVER_TAG;// abnormal case
        }

        private void processCheckLedData(object data)
        {
            LedStatusViewer viewer = new LedStatusViewer(ledStatusWidth, ledStatusHeight, ledStatusData);
            viewer.StartPosition = FormStartPosition.CenterParent;
            viewer.ShowDialog();
        }

        byte ledStatusPackageCount = 0;
        int currentLedStatusPackageIndex = 0;
        int ledStatusDataLength = 0;
        ushort ledStatusWidth = 0;
        ushort ledStatusHeight = 0;
        byte[] ledStatusData;
        bool isCheckLedMode = false;

        ushort LED_STATUS_DATA_PACKAGE_LENGTH = 1000;
        public void DisconnectClient(String remoteIP, String remotePort)
        {
            try
            {
                //String remoteIP1 = "", remotePort1 = "";
                //UpdateClientList(r6emoteIP + " : " + remotePort, "Delete");

                int counter = 0;

                //remove client from allList
                counter = 0;
                // tungpt modified >>

                //foreach (Socket sock in AllSocketList)
                foreach (BaseDevice dev in listDevice)
                // << ended
                {
                    if (dev.GetType() == typeof(TCPDevice))
                    {
                        if (((TCPDevice)dev).IP.Equals(remoteIP) && ((TCPDevice)dev).Port.ToString().Equals(remotePort))
                            break;
                    }
                    counter++;
                }
                if (counter < listDevice.Count)
                {
                    //SetInfo(remoteIP + "\\" + remotePort, "Disconnected!");
                    // TODO: disconnect socket
                    listDevice[counter].close();
                    //DataList.RemoveAt(counter);
                    //System.Threading.Thread.Sleep(5000);// sleep for finish synchronous process

                    //((Thread)(threadArray[counter])).Abort();
                    //threadArray.RemoveAt(counter);
                }
            }
            catch (System.Exception ex)
            {
                Debug.WriteLine("Mainform 555: " + ex.Message);
            }
        }
        /// Function checks whether to start or stop the server
        #endregion
        
        #region | Show/Hide button events |
        /// <summary>
        /// Handle event when user click on Home button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        private void btnHome_Click(object sender, EventArgs e)
        {
            if (!homePanel.Visible)
                showHomePanel();
        }

        /// <summary>
        /// Handle event when user click on "Devices" or "Programs" tab
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        private void tabContent_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tabContent.SelectedTab == tabContent.TabPages["tabDevices"])
            {
                // populate device list
                populateDeviceList();
                // show device panel
                showDevicesPanel();
                
            }
            else if (tabContent.SelectedTab == tabContent.TabPages["tabPrograms"])
            {
                // TODO: show first program detail
                // show program panel
                showProgramPanel();
            }
        }

        /// <summary>
        /// Show home panel and dispose other panel
        /// </summary>
        /// <returns></returns>
        private void showHomePanel()
        {
            homePanel.Visible = true;
            //devicesPanel.Visible = false;
            deviceDetailsPanel.Visible = false;
            progPanel.Visible = false;
            tabContent.SelectedIndex = -1;// tabContent.TabPages["tabPrograms"];
        }

        /// <summary>
        /// Show device list panel and dispose other panel
        /// </summary>
        /// <returns></returns>
        private void showDevicesPanel()
        {
            homePanel.Visible = false;
            deviceDetailsPanel.Visible = false;
            progPanel.Visible = false;
            //devicesPanel.Visible = true;
        }

        /// <summary>
        /// Show program list panel and dispose other panel
        /// </summary>
        /// <returns></returns>
        private void showProgramPanel()
        {
            homePanel.Visible = false;
            deviceDetailsPanel.Visible = false;
            progPanel.Visible = true;
            //devicesPanel.Visible = false;
        }

        /// <summary>
        /// Show device's detail at selected index
        /// </summary>
        /// <param name="index">index to be displayes</param>
        /// <returns></returns>
        private void showDeviceDetails(int index)
        {
            deviceDetailsPanel.DeviceInfo = listDevice[index];

            // show panel
            homePanel.Visible = false;
            //devicesPanel.Visible = false;
            progPanel.Visible = false;
            deviceDetailsPanel.Visible = true;
        }
        #endregion

        #region | populate listview |
        /// <summary>
        /// Get device data and display to listview
        /// </summary>
        /// <returns></returns>
        private void populateDeviceList()
        {
            if (listDevice.Count < 0)
                return;

            // update item in list
            listViewDevices.BeginUpdate();
            // clear old items
            listViewDevices.Items.Clear();

            foreach (BaseDevice b in listDevice)
            {
                // 0 and 1 are image index in imagelist
                ListViewItem item = new ListViewItem(b.Name, b.Type == DEVICE_TYPE.SMS ? 0 : 1);
                listViewDevices.Items.Add(item);
                Logger.Instance.Register(b);
            }
            
            listViewDevices.EndUpdate();
        }

        private List<BaseDevice> listDevice;

        private void populatePlayList()
        {
            if (playlist == null || playlist.Count <= 0)
                return;

            // update item in list
            playlistTreeView.BeginUpdate();
            // clear old items
            //playlistTreeView.Items.Clear();

            foreach (PlaylistData pl in playlist)
            {
                TreeNode[] progNodes = new TreeNode[pl.Info.PackageCount];
                int i = 0;
                foreach(ProgramData prog in pl.packages)
                {
                    progNodes[i] = new TreeNode("program " + i);
                    i++;
                }
                playlistTreeView.Nodes.Add(new TreeNode(pl.Name,progNodes));
            }

            playlistTreeView.EndUpdate();
        }
        List<PlaylistData> playlist;
        private void populatePlayListNew()
        {
            if (playlistnew == null || playlistnew.Count <= 0)
                return;

            // update item in list
            playlistTreeView.BeginUpdate();
            // clear old items
            //playlistTreeView.Items.Clear();

            foreach (LedPlaylist pl in playlistnew)
            {
                TreeNode[] progNodes = new TreeNode[pl.Count];
                int i = 0;
                foreach (BaseProgram prog in pl)
                {
                    progNodes[i] = new TreeNode(prog.Type.ToString());
                    i++;
                }
                playlistTreeView.Nodes.Add(new TreeNode(pl.Name, progNodes));
            }

            playlistTreeView.EndUpdate();
        }
        private List<LedPlaylist> playlistnew;
        #endregion

        /// <summary>
        /// Load Test data
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        private void MainForm_Load(object sender, EventArgs e)
        {
            // for test purpse
            // start test >>
            /*
            listDevice = new List<BaseDevice>();
#if TEST_OFFLINE

            TCPDevice dev = new TCPDevice("TCP 1", "12345", "192.168.175.175", 6868);
            dev.DataTimeout += new DataTimeoutHandler(MainForm_DataTimeout);
            listDevice.Add(dev);
#else
            listDevice.Add(new TCPDevice("TCP 1", "12345", "192.168.175.175", 6868));
#endif
            listDevice.Add(new TCPDevice("TCP 2", "12345", "192.168.175.35", 6868));
            listDevice.Add(new SMSDevice("SMS 1", "12345", "+84919992959", SMS_MODE.PDU));
            listDevice.Add(new TCPDevice("TCP 3", "12345", "192.168.1.12", 6868));
            listDevice.Add(new SMSDevice("SMS 2", "12345", "0168773591", SMS_MODE.PLAINTEXT));

            listDevice.Add(new TCPDevice("TCP 4", "12345", "192.168.175.36", 6868));
            listDevice.Add(new SMSDevice("SMS 3", "12345", "+84919992950", SMS_MODE.PDU));
            listDevice.Add(new TCPDevice("TCP 5", "12345", "192.168.1.13", 6868));
            listDevice.Add(new SMSDevice("SMS 4", "12345", "0168773592", SMS_MODE.PLAINTEXT));
            listDevice.Add(new TCPDevice("TCP 6", "12345", "192.168.1.13", 6868));
            listDevice.Add(new TCPDevice("TCP 7", "12345", "192.168.1.13", 6868));
            listDevice.Add(new TCPDevice("TCP 8", "12345", "192.168.1.13", 6868));
            listDevice.Add(new TCPDevice("TCP 9", "12345", "192.168.1.13", 6868));
            listDevice.Add(new TCPDevice("TCP 10", "12345", "192.168.1.13", 6868));
            listDevice.Add(new TCPDevice("TCP 11", "12345", "192.168.1.13", 6868));
            */
            // << end test
            listDevice = XmlDatabase.Instance.getDevices();
            populateDeviceList();
            /*
             * old solution >>
            playlist = XmlDatabase.Instance.getPlaylists();
            populatePlayList();
             * << end
            */
            playlistnew = XmlDatabase.Instance.getPlaylistsNew();
            populatePlayListNew();
        }

        private void listViewDevices_ItemActivate(object sender, EventArgs e)
        {
            // TODO: display device detail when double-click on item
            return;
        }
        int lastSeletecteIndex = -1;
        private void listViewDevices_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            // TODO: display device detail at selected index
            if (listViewDevices.SelectedIndices.Count <= 0)
            {
                btnDelete.Enabled = false;
                return;
            }
            lastSeletecteIndex = listViewDevices.SelectedIndices[0];

            if (lastSeletecteIndex >= 0)
            {
                btnDelete.Enabled = true;
                showDeviceDetails(lastSeletecteIndex);
            } 
            
            return;
        }

        /// <summary>
        /// Add new device
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        private void btnAdd_Click(object sender, EventArgs e)
        {
            if (tabContent.SelectedTab == tabContent.TabPages["tabDevices"])
            {
                DeviceForm dForm = new DeviceForm();
                if (dForm.ShowDialog() == DialogResult.OK)
                {
                    // add device info to list
                    listDevice.Add(dForm.DeviceInfo);
                    // populate to listview
                    populateDeviceList();
                    // TODO: save password

                }
            }
            else if (tabContent.SelectedTab == tabContent.TabPages["tabPrograms"])
            {
                CreateLedProgram dForm = new CreateLedProgram();
                if (dForm.ShowDialog() == DialogResult.OK)
                {
                    // add device info to list
                    //listDevice.Add(dForm.DeviceInfo);
                    // populate to listview
                    //populateDeviceList();
                    // TODO: save password

                }
            }
        }

        TreeNode lastClickedNode;
        private void playlistTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            //return;
            if (lastClickedNode == e.Node) return;
            // root level = click to view playlist
            if (e.Node.Level == 0)
            {
                progPanel.setThumbnailMode(true);
                int index = indexOfNode(e.Node);
                // tungpt changed >>
                // progPanel.populatePlaylist(playlist[index]);
                progPanel.currentMode = PROGRAM_MODE.PLAYLIST;
                progPanel.populatePlaylistNew(playlistnew[index]);
                // << end
            }
            else // program level to view program data
            {
                int parentIndex = indexOfNode(e.Node.Parent);
                int nodeIndex = indexOfNode(e.Node);
                progPanel.setThumbnailMode(false);
                // tungpt changed >>
                //progPanel.populateProgram(playlist[index]);
                progPanel.currentMode = PROGRAM_MODE.TEXT;
                progPanel.populateProgram(playlistnew[parentIndex][nodeIndex]);
                // << end
            }
            lastClickedNode = e.Node;
        }
        int indexOfNode(TreeNode tn)
        {
            TreeNode parent = tn.Parent;
            if (null != parent)
                return parent.Nodes.IndexOf(tn);
            return playlistTreeView.Nodes.IndexOf(tn);
        }
         
        private void updateFirmwareToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // allow user to choose firmware file
            OpenFileDialog firmwareChooser = new OpenFileDialog();
            firmwareChooser.Filter = "hex file|*.hex| All | *.*";

            string firmwarePath = "";
            BlackboxFirmware bFirmware = null ;
            if (firmwareChooser.ShowDialog() == DialogResult.OK)
            {
                firmwarePath = firmwareChooser.FileName;
                if (File.Exists(firmwarePath))
                    bFirmware = new BlackboxFirmware(firmwarePath);
                else 
                {
                    Debug.WriteLine("Firmware path not exists!");
                    return;
                }

                // allow user to choose which devices need to updated and send update data
                foreach (TCPDevice dev in selectTCPDevices())
                {
                    // call update firmware routies
                    if (dev != null && dev.isActive && bFirmware != null)
                        dev.sendFirmware(bFirmware);
                    else
                    {
                        MessageBox.Show("Please check device status!");
                    }
                }
            }
            
        }

        private void updatefontToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // allow user to choose firmware file
            OpenFileDialog fontChooser = new OpenFileDialog();
            fontChooser.Filter = "bin file|*.bin | font file|*.font| all file|*.*";

            string fontPath = "";
            //BlackboxFirmware bFirmware = null; 
            if (fontChooser.ShowDialog() == DialogResult.OK)
            {
                fontPath = fontChooser.FileName;
                if (!File.Exists(fontPath))
                {
                    Debug.WriteLine("Firmware path not exists!");
                    return;
                }

                // allow user to choose which devices need to updated and send update data
                foreach (TCPDevice dev in selectTCPDevices())
                {
                    // call update firmware routies
                    if (dev != null && dev.isActive)
                    {
                        // call update firmware 
                        dev.sendFontData(new FontFirmware(fontPath));
                    }
                    else
                    {
                        MessageBox.Show("Please check device status!");
                    }
                    
                }
            }
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            StopServer();
        }

        private void englishToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ChangeLanguage("en");
        }

        private void tiếngViệtToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ChangeLanguage("vi");
        }

        private void ChangeLanguage(string lang)
        {
            foreach (Control c in this.Controls)
            {
                ComponentResourceManager resources = new ComponentResourceManager(typeof(MainForm));
                resources.ApplyResources(c, c.Name, new CultureInfo(lang));
            }
        }

        private void ShowNotify(String message)
        {

            //notifyIcon.BalloonTipIcon = ToolTipIcon.Info;
            notifyIcon.BalloonTipText = message;
            //notifyIcon.BalloonTipTitle = "Welcome Message";
            //notifyIcon.Visible = true;
            notifyIcon.ShowBalloonTip(1000);
            //notifyIcon.Visible = false;
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show(
                    "Are you sure want to quit this application?",
                    "Quit application",
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question) == DialogResult.Yes)
            {
                Application.Exit();
            }
        }

        
    }
}
/*
<LedData>
    <DataInfo>
        <ID></ID>
        <ObjectCount></ObjectCount>
        <StartDate></StartDate>
        <EndDate></EndDate>
    </DataInfo>
    <Objectdata ID="1" X="10" Y="10" Width="20" Height="20" Delay="5" Type="IMAGE" Effect="1"> 
        <Image Width="100" Height="20" Bpp="2">
            .....        
        </Image>
    </Objectdata>
    <Objectdata ID="2" X="20" Y="30" Width="50" Height="50" Delay="5" Type="CLOCK" Effect="0" />
    <Objectdata ID="3" X="70" Y="30" Width="50" Height="50" Delay="5" Type="TEMP" Effect="0" />
    <Objectdata ID="3" X="100" Y="0" Width="150" Height="80" Delay="5" Type="PLAYLIST" Effect="0" >
        1 
    </ObjectData>
    <Background Width="100" Height="20" Bpp="2">
        ........
    </Background>
</LedData>
*/